using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using GammaJul.ReSharper.GammaXaml.Highlightings.Xaml;
using JetBrains.Annotations;
using JetBrains.ProjectModel;
using JetBrains.ReSharper.Daemon;
using JetBrains.ReSharper.Psi;
using JetBrains.ReSharper.Psi.Xaml.Impl.Tree;

[assembly: RegisterConfigurableSeverity(
	MeaninglessAttachedSetterForTypeHighlighting.SeverityId,
	null,
	HighlightingGroupIds.CodeRedundancy,
	MeaninglessAttachedSetterForTypeHighlighting.Description,
	MeaninglessAttachedSetterForTypeHighlighting.Description,
	Severity.SUGGESTION,
	false)]

namespace GammaJul.ReSharper.GammaXaml.Highlightings.Xaml {

	/// <summary>
	/// An highlighting that indicates that an attached setter has no meaning unless it's on some specific types.
	/// </summary>
	[ConfigurableSeverityHighlighting(SeverityId, XamlProjectFileType.Name, AttributeId = HighlightingAttributeIds.DEADCODE_ATTRIBUTE, OverlapResolve = OverlapResolveKind.DEADCODE)]
	public class MeaninglessAttachedSetterForTypeHighlighting : MeaninglessAttachedSetterHighlightingBase {
		internal const string SeverityId = "Xaml.MeaninglessAttachedSetterForType";
		internal const string Description = "An attached property setter only have a meaning on a specific type.";

		private readonly IList<ITypeElement> _expectedTypes;

		[NotNull]
		public IList<ITypeElement> ExpectedTypes {
			get { return _expectedTypes; }
		}

		protected override string GetToolTipEnd() {
			var builder = new StringBuilder();
			for (int i = 0; i < _expectedTypes.Count; ++i) {
				if (i > 0)
					builder.Append(" or ");
				builder.Append('\'');
				builder.Append(_expectedTypes[i].GetClrName().FullName);
				builder.Append('\'');
			}
			return builder.ToString();
		}

		public override bool IsValid() {
			return base.IsValid() && _expectedTypes.All(type => type.IsValid());
		}

		public MeaninglessAttachedSetterForTypeHighlighting([NotNull] IPropertySetter propertySetter, [NotNull] IMethod attachedSetter, [NotNull] IList<ITypeElement> expectedTypes)
			: base(propertySetter, attachedSetter) {
			if (expectedTypes == null)
				throw new ArgumentNullException("expectedTypes");

			_expectedTypes = expectedTypes;
		}
	}

}
